﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Hsp.Auto.Model.Data
{
    public static class DataTableExtentions
    {
        public static List<T>? ToList<T>(this DataTable dataTable) where T : new()
        {
            var list = new List<T>();

            foreach (DataRow row in dataTable.Rows)
            {
                var item = new T();

                foreach (DataColumn column in dataTable.Columns)
                {
                    var property = item.GetType().GetProperty(column.ColumnName);
                    if (property != null && row[column] != DBNull.Value)
                    {
                        property.SetValue(item, row[column], null);
                    }
                }

                list.Add(item);
            }

            return list;
        }


        /// <summary>
        /// DataTable转成List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static IEnumerable<T>? ToEnumerable<T>(this DataTable dt) where T : class, new()
        {
            PropertyInfo[] propertyInfos = typeof(T).GetProperties();
            T[] ts = new T[dt.Rows.Count];
            int i = 0;
            foreach (DataRow row in dt.Rows)
            {
                T t = new T();
                foreach (PropertyInfo? prop in propertyInfos)
                {
                    //if (dt.Columns.IndexOf(p.Name) != -1 && row[p.Name] != DBNull.Value)
                    //    p.SetValue(t, row[p.Name], null);

                    try
                    {
                        if (!prop.PropertyType.IsPublic || !prop.CanWrite || !dt.Columns.Contains(prop.Name) || row[prop.Name] == DBNull.Value) continue;

                        object? value = (row[prop.Name] == DBNull.Value) ? null : row[prop.Name];

                        if (prop.PropertyType.Name == "Guid")
                        {
                            value = (row[prop.Name] == DBNull.Value) ? default : new Guid(row[prop.Name].ToString()!);
                        }

                        if (prop.PropertyType.Name == "Nullable`1")
                        {
                            string? fullName = prop.PropertyType.FullName;
                            bool isInt = (fullName?.Contains("System.Int32") ?? false) || (fullName?.Contains("System.Int64") ?? false);
                            bool isDouble = fullName?.Contains("System.Double") ?? false;
                            if (isInt) value = value == null ? 0 : Convert.ToInt32(value);
                            if (isDouble) value = value == null ? 0 : Convert.ToDouble(value);
                        }

                        if (prop?.GetMethod?.ReturnParameter?.ParameterType?.Name == "Int32")
                        {
                            value = value == null ? 0 : Convert.ToInt32(value);
                        }

                        if (prop?.GetMethod?.ReturnParameter?.ParameterType?.Name == "Int64")
                        {
                            value = value == null ? 0 : Convert.ToInt32(value);
                        }

                        if (prop?.PropertyType?.Name == "String")
                        {
                            prop?.SetValue(t, value?.ToString());
                        }
                        else
                        {
                            prop?.SetValue(t, SqlNull(value!));
                        }
                    }
                    catch (Exception)
                    {
                        //throw;
                    }

                }
                ts[i] = t;
                i++;
            }
            return ts;
        }


        #region SqlNull

        /// <summary>
        /// SqlNull
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static object SqlNull(object obj)
        {
            if (obj == null || obj.ToString() == "")
            {
                return DBNull.Value;
            }
            else
            {
                return obj;
            }
        }

        #endregion
    }
}
